package com.googlecode.beanfiles.translators;

import java.util.List;

import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.beanfiles.TranslationArgumentException;
import com.googlecode.beanfiles.TranslationException;


/**
 * A Translator that uses the BeanUtils library's ConvertUtils class for translation. This is an extremely useful simple property conversion
 * because the BeanUtils library provides the conversion implementations. If BeanUtils does not provide a suitable conversion out of the
 * box, a Converter can be registered with something like:
 * 
 * <pre>
 *      ConvertUtils.register(new ListConverter(), java.util.List.class);
 * </pre> 
 * 
 * Note that there are some library provided converters within the org.keester.bfconversions.utils package.
 * 
 * BeanUtils converters should catch Exceptions and rethrow as TranslationArgumentExceptions, if they need TranslationNotices
 * with accurate information (i.e., the value that could not be converted).
 * 
 * <p>For instance:</p>
 * <pre>
 *      try {
 *          // process value ...
 *      } catch (IllegalArgumentException e) {
 *          throw new TranslationArgumentException("invalid value", value, e);
 *      }
 * </pre>
 */
public class ConvertUtilsTranslator extends IndexedTranslator {

    protected static Log log() {
        return LogFactory.getLog(ConvertUtilsTranslator.class);
    }

    public ConvertUtilsTranslator(String propertyName, int index) {
        super(propertyName, index);
    }

    /**
     * Returns a BeanUtils conversion of the value at i[index].
     */
    @Override
    public Object read(Object i, Class<?> clazz) {
        Converter converter = ConvertUtils.lookup(clazz);
        if (converter == null) {
            throw new TranslationException("No BeanUtils converter registered for class: " + clazz.getName());
        }
        Object o = ((List<?>) i).get(this.indexes.get(0));
        addNoticeIfNull(o);
        try {
        	return converter.convert(clazz, o);
        } catch (ConversionException e) {
        	throw new TranslationArgumentException(e, o);
        }
    }

    @Override
    public Object write(Object t) {
        throw new UnsupportedOperationException("method not supported");
    }

}
